#include "TcpServer.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h> //posix网络编程
#include <strings.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include "TcpSocket.h"
#include "MessageDto.h"
#include <glib.h>

using namespace std;

typedef struct sockaddr_in sockaddr_in;
typedef struct sockaddr sockaddr;
typedef struct epoll_event epoll_event;

TcpServer::TcpServer():TcpServer(8080)
{
}

TcpServer::TcpServer(int port)
{
    this->serverFd=socket(AF_INET,SOCK_STREAM,0);
    if (serverFd==-1)
    {
        cout<<"创建失败"<<endl;
        return;
    }
    
    //创建地址结构体对象
    sockaddr_in serverAddr;
    int addrsize=sizeof(sockaddr_in);
    serverAddr.sin_family=AF_INET;
    serverAddr.sin_port=htons(port);
    serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);

    //绑定地址和文件描述符
    int retVal=bind(serverFd,(sockaddr*)&serverAddr,addrsize);
    if (retVal==-1)
    {
        cout<<"绑定失败"<<endl;
        return;
    }
    //监听
    retVal=listen(serverFd,10);//最大同时接收10个请求
    if (retVal==-1)
    {
        cout<<"监听失败"<<endl;
        return;
    }
    //创建epoll实例
    this->epollId=epoll_create(100);
    if (epollId==-1)
    {
        cout<<"epoll创建失败"<<endl;
        return;
    }
    epoll_event event;
    event.events=EPOLLIN;
    event.data.fd=serverFd;
    epoll_ctl(epollId,EPOLL_CTL_ADD,serverFd,&event);

}

TcpServer::~TcpServer()
{
    if (this->serverFd>0)
    {
        close(this->serverFd);
    }
    
}

void TcpServer::start(void*(*fn)(void *))
{
    epoll_event evs[1024];
    while (1)
    {
        int ret=epoll_wait(this->epollId,evs,1024,3000);
        if (ret==-1)
        {
            cout<<"epoll失败"<<endl;
            continue;
        }else if (ret==0)
        {
            continue;
        }
        for (int i = 0; i < ret; i++)
        {
            int fd=evs[i].data.fd;
            if (serverFd==fd)
            {
                this->acceptConn();
                continue;
            }
            if (evs[i].events & EPOLLOUT)
            {
                continue;
            }
            TcpSocket *socket=new TcpSocket(fd);
            MessageDto *dto=new MessageDto(socket,fd,this->epollId);
            pthread_t tid;
            pthread_create(&tid,NULL,fn,dto);
        }
    }
}

void TcpServer::startWithPool(GFunc func)
{
    epoll_event evs[1024];
    GThreadPool *pool=g_thread_pool_new(func,NULL,16,FALSE,NULL);
    while (1)
    {
        int ret=epoll_wait(this->epollId,evs,1024,3000);
        if (ret==-1)
        {
            cout<<"epoll失败"<<endl;
            continue;
        }else if (ret==0)
        {
            continue;
        }
        for (int i = 0; i < ret; i++)
        {
            int fd=evs[i].data.fd;
            if (serverFd==fd)
            {
                this->acceptConn();
                continue;
            }
            if (evs[i].events & EPOLLOUT)
            {
                continue;
            }
            TcpSocket *socket=new TcpSocket(fd);
            MessageDto *dto=new MessageDto(socket,fd,this->epollId);
            g_thread_pool_push(pool,dto,NULL);
        }
    }
}

void TcpServer::acceptConn()
{
    int addrsize=sizeof(sockaddr_in);
    sockaddr_in clientAddr;
    int clientFd=accept(serverFd,(sockaddr*)&clientAddr,(socklen_t*)&addrsize);
    cout<<inet_ntoa(clientAddr.sin_addr)<<":"<<ntohs(clientAddr.sin_port)<<endl;
    //边沿触发
    int flag=fcntl(clientFd,F_GETFL);
    flag | O_NONBLOCK;
    fcntl(clientFd,F_SETFL,flag);

    epoll_event event;
    event.data.fd=clientFd;
    event.events=EPOLLIN | EPOLLET;
    epoll_ctl(epollId,EPOLL_CTL_ADD,clientFd,&event);
}
